package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"fmt"
)

/**
  AES 加密和解密
*/

func PKCS5Padding(cipherText []byte, blockSize int) []byte {
	padding := blockSize - len(cipherText)                  //剩余的字节
	padText := bytes.Repeat([]byte{byte(padding)}, padding) //补充位数的数据
	return append(cipherText, padText...)                   //追加数据
}

func PKCS5UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])   //取出补充的位数
	return origData[:(length - unpadding)] //剪接数据
}

//加密
func AesEncrypt(origData, key []byte) ([]byte, error) {

	block, err := aes.NewCipher(key) //创建密码 根据秘钥加密
	if err != nil {
		return nil, err
	}

	blockSize := block.BlockSize()                              //定义大小
	origData = ZeroPadding(origData, block.BlockSize())         //补充位数
	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) //创建加密算法
	cryped := make([]byte, len(origData))                       //加密
	blockMode.CryptBlocks(cryped, origData)                     //按照区块加密
	return cryped, nil
}

//解密
func AesDecrypt(cryptData, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err //创建一个密码，处理错误
	}
	blockSize := block.BlockSize()                              //定义大小
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) //解码算法
	orgdData := make([]byte, len(cryptData))                    //创建空间
	blockMode.CryptBlocks(orgdData, cryptData)                  //解密
	orgdData = ZeroUnPadding(orgdData)                          //去除尾部的补充数的数据
	return orgdData, nil

}

//AES对称加密，不足128位用0补充

func ZeroPadding(cipherText []byte, blockSize int) []byte {
	padding := blockSize - len(cipherText)%blockSize //填充的长度
	padText := bytes.Repeat([]byte{'*'}, padding)    //填充0
	return append(cipherText, padText...)            //字节叠加
}

func ZeroUnPadding(origData []byte) []byte { //删除填充数据

	return bytes.TrimRightFunc(origData, func(r rune) bool {
		return r == rune('*')
	})
}
func main() {
	fmt.Println("game start")
	//AES128, 16 24 32 AES128 192 256
	key := []byte("yinchenglovegogo")
	result, err := AesEncrypt([]byte("QQ77025077"), key) //
	if err != nil {
		panic(err) //处理异常
	}
	fmt.Println(base64.StdEncoding.EncodeToString(result)) //加密以后的数据
	origdata, err := AesDecrypt(result, key)               //解密
	if err != nil {
		panic(err)
	}
	fmt.Println(string(origdata))
}
